/*
*	Project: Aethon
*
*	File: Control.cpp
*
*	Author: Jonathan Hersack
*
*	Date: 2/15/2009
*
*   Purpose: The Control handles the keyboard/mouse input for the 
*   user-to-model interaction
*/

#include "../include/Control.h"

	//#############################################################
	void Control::keyboardHandle(unsigned char key, int x, int y)
    {//use unit vector model.direction to increment velocity in correct direction
	//by using a differential velocity passed to updateVelocity
	
switch(key)
   {    
   case 'w': 
   case 'W': diffVel.v[2] +=1;
   //cout << diffVel.v[2] <<" z forward pressed"<< endl;
   //cout << key <<" pressed"<< endl;
   glutPostRedisplay();
             break;
   case 'a':
   case 'A': 
    diffVel.v[0] -=1;
   //cout << diffVel.v[0] <<" x  right pressed"<< endl;
   //cout << key <<" pressed"<< endl;
   glutPostRedisplay();
             break;
   case 's':
   case 'S': 
   diffVel.v[2] -=1;
   //cout << diffVel.v[2] <<" z forward pressed"<< endl;
   //cout << key <<" pressed"<< endl;
   glutPostRedisplay();
             break;
   case 'd':
   case 'D': 
   diffVel.v[0] +=1;
   //cout << diffVel.v[0] <<" x  right pressed"<< endl;
   //cout << key <<" pressed"<< endl;
   glutPostRedisplay();
             break;      
   case 'o':
   case 'O': 
   diffDir.v[0] -=1;
   //cout << diffDir.v[0] <<" y  right pressed"<< endl;
   //cout << key <<" pressed"<< endl;
   glutPostRedisplay();
             break; 
   case 'l':
   case 'L': 
   diffDir.v[0] +=1;
   //cout << diffDir.v[0] <<" y  right pressed"<< endl;
   //cout << key <<" pressed"<< endl;
   glutPostRedisplay();
             break; 
   case 'k':
   case 'K': 
   diffDir.v[1] -=1;
   //cout << diffDir.v[1] <<" x  right pressed"<< endl;
   //cout << key <<" pressed"<< endl;
   glutPostRedisplay();
             break;
   case ';':
   case ':': 
   diffDir.v[1] +=1;
   //cout << diffDir.v[1] <<" x  right pressed"<< endl;
   //cout << key <<" pressed"<< endl;
   glutPostRedisplay();
             break;		 
   case 'q':
   case 'Q':  exit(0);
			 break;
   default:
            cout << key << endl;
   } // End switch
    //Note on diffVel, it is treated as 
	//a straight 3d coord, with +-z always  
	//forwards and backwards of current direction
	//y up/down, x left/right
	
    }//end keyboardhandle

	//#############################################################
	void Control::mouseHandle(int x, int y)
    {
 		 
		 diffDir.v[0] = InvertedLook*((y - lastY)/PixelDegreeFactor);//set change in x rotation, inverted look is either 1 or -1
		 diffDir.v[1] = InvertedHorizLook*((x - lastX)/PixelDegreeFactor);//set change in y rotation
		 lastX = x;
		 lastY = y;	
		 
		 if(x > (320 + DeadZone) || x < (320 - DeadZone) || y > (240 + DeadZone) || y < (240 - DeadZone))
		 {
		glutWarpPointer(320,240);
		 }
		 glutPostRedisplay();		
		 
    }//end mouseHandle

	
	//#############################################################
	void Control::updateVelocity()
	{
	vector3f currentVel = modelPtr->getVelocity();
	
	//get forward vector from direction.
	vector3f tempvect = calcPoints(modelPtr->getDirection());
	
	//tempvect.v[1] = 0;//not moving up unless jumping,ignore for now
	tempvect = normalizeVector(tempvect);
		
	//next use cross(up,forward) = strafe vector for changing perpendicular vel

	tempvect.v[0] = currentVel.v[0]+(tempvect.v[0]*diffVel.v[2]);
	tempvect.v[1] = currentVel.v[1]+(tempvect.v[1]*diffVel.v[2]);
	tempvect.v[2] = currentVel.v[2]+(tempvect.v[2]*diffVel.v[2]);
	
	modelPtr->setVelocity(tempvect);
	vector3f resetVect(0,0,0);
	setDiffVel(resetVect);
	//cout<<"vel updated"<<endl;
	}//end updateVelocity

	
	//#############################################################
	void Control::updateDirection()
	{
	
	vector3f tempvect;
	tempvect = modelPtr->getDirection();
	tempvect.v[0] = tempvect.v[0]+diffDir.v[0];//x rotation of model
	
	if(tempvect.v[0]>90)
	{tempvect.v[0]=90;}//end if
	else if(tempvect.v[0]<-90)
	{tempvect.v[0]=-90;}//end if
	
	tempvect.v[1] = tempvect.v[1]+diffDir.v[1];//y rotation of model
	if(tempvect.v[1]>360)
	{tempvect.v[1]-=360;}//end if
	else if(tempvect.v[1]<0)
	{tempvect.v[1]+=360;}//end if
	
	modelPtr->setDirection(tempvect);
	vector3f resetVect(0,0,0);
	setDiffDir(resetVect);
	
	}//end updateDirection

//####################################################################	
	vector3f Control::calcPoints(vector3f angles)
	{
	//uses Y*X rotation matrices
	vector3f forwardVect;
	float xPoint = cos(angles.v[1]*PI/180.0) + sin(angles.v[0]*PI/180.0)*sin(angles.v[1]*PI/180.0)
	- cos(angles.v[0]*PI/180.0)*sin(angles.v[1]*PI/180.0);
	
	float yPoint = 0 +  cos(angles.v[0]*PI/180.0)+sin(angles.v[0]*PI/180.0);
	
	float zPoint = sin(angles.v[1]*PI/180.0) - sin(angles.v[0]*PI/180.0) * cos(angles.v[1]*PI/180.0)
	+ cos(angles.v[0]*PI/180.0)*cos(angles.v[1]*PI/180.0);
 

	forwardVect.v[0]=xPoint;
	forwardVect.v[1]=yPoint;
	forwardVect.v[2]=zPoint;
	
	return forwardVect;
	}//end calcpoints
	
//####################################################################
	vector3f Control::normalizeVector(vector3f vect)
	{
	float magnitude = sqrt(vect.v[0]*vect.v[0]+vect.v[1]*vect.v[1]+vect.v[2]*vect.v[2]);
	vector3f unitVect;
	unitVect.v[0]=vect.v[0]/magnitude;
	unitVect.v[1]=vect.v[1]/magnitude;
	unitVect.v[2]=vect.v[2]/magnitude;
	return unitVect;
	}//end normailzevector
	